﻿using MediatR;
using SuYuanRabbit.Domain.Entities.RBAC;
using SuYuanRabbit.ErrorCode;
using SuYuanRabbit.Infrastructure.Interfaces;
using SuYuanRabbit.ReadAPI.Applications.Commands.Login;
using SuYuanRabbit.ReadAPI.Dtos.Response;

namespace SuYuanRabbit.ReadAPI.Applications.CommandsHanders.Login
{
    /// <summary>
    /// 登录处理
    /// </summary>
    public class LoginHander : IRequestHandler<LoginCommandHander, ApiResult<UserDto>>
    {
        /// <summary>
        /// 用户仓储
        /// </summary>
        private readonly IBaseRepository<User> userRepository;
        /// <summary>
        /// 角色仓储
        /// </summary>
        private readonly IBaseRepository<Role> roleRepository;
        /// <summary>
        /// 角色用户仓储
        /// </summary>
        private readonly IBaseRepository<RoleUser> roleUserRepository;
        /// <summary>
        /// 权限仓储
        /// </summary>
        private readonly IBaseRepository<Permission> permissionRepository;
        /// <summary>
        /// 角色权限仓储
        /// </summary>
        private readonly IBaseRepository<RolePermission> rolePermissionRepository;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="userRepository">用户仓储</param>
        /// <param name="roleRepository">角色仓储</param>
        /// <param name="roleUserRepository">角色用户仓储</param>
        /// <param name="permissionRepository">权限仓储</param>
        /// <param name="rolePermissionRepository">角色权限仓储</param>
        public LoginHander(IBaseRepository<User> userRepository, IBaseRepository<Role> roleRepository, IBaseRepository<RoleUser> roleUserRepository, IBaseRepository<Permission> permissionRepository, IBaseRepository<RolePermission> rolePermissionRepository)
        {
            this.userRepository = userRepository;
            this.roleRepository = roleRepository;
            this.roleUserRepository = roleUserRepository;
            this.permissionRepository = permissionRepository;
            this.rolePermissionRepository = rolePermissionRepository;
        }

        /// <summary>
        /// 处理
        /// </summary>
        /// <param name="request">请求</param>
        /// <param name="cancellationToken">取消</param>
        /// <returns>返回任务</returns>
        public async Task<ApiResult<UserDto>> Handle(LoginCommandHander request, CancellationToken cancellationToken)
        {
            /*//查询指定用户(提高性能)
            var users = await userRepository.FindAsync(x=>x.UserAccount == request.Account);
            var user = users.FirstOrDefault(u => u.UserAccount == request.Account);
            //判断用户是否存在
            if (user == null)
            {
                return await Task.FromResult(new ApiResult<UserDto>
                {
                    Code = EnumCode.notfound,
                    Message = "用户不存在"
                });
            }
            //判断密码是否正确
            if (request.Password != user.UserPassword)
            {
                if (user.ErrorNums > 3)
                {
                    user.IsLocked = true;
                    await userRepository.UpdateAsync(user);
                    return await Task.FromResult(new ApiResult<UserDto>
                    {
                        Code = EnumCode.error,
                        Message = "用户已被锁定"
                    });
                }
                user.ErrorNums += 1;
                await userRepository.UpdateAsync(user);
                return await Task.FromResult(new ApiResult<UserDto>
                {
                    Code = EnumCode.error,
                    Message = "密码错误" + user.ErrorNums + "次,还有" +
                    (4 - user.ErrorNums) + "次机会。"
                });
            }

            var linq = from U in await userRepository.GetAll()
                       join Ru in await roleUserRepository.GetAll() on
                       U.UserId equals Ru.UserId
                       join R in await roleRepository.GetAll() on
                       Ru.RoleId equals R.RoleId
                       join Rp in await rolePermissionRepository.GetAll() on
                       R.RoleId equals Rp.RoleId
                       join P in await permissionRepository.GetAll() on
                       Rp.PermissionId equals P.PermissionId
                       select new UserDto
                       {
                           Account = U.UserAccount,
                           UserNickName = U.UserNickName,
                           RoleId = R.RoleId,
                           RoleName = R.RoleName,
                           PermissionId = P.PermissionId,
                           PermissionName = P.PermissionName
                       };
            var dto = linq.FirstOrDefault(u => u.Account == request.Account);
            return await Task.FromResult(new ApiResult<UserDto>
            {
                Code = EnumCode.success,
                Message = "登录成功",
                Data = dto
            });*/
            // 使用 FindAsync 方法直接查询指定账户的用户(最优解)
            var user_ = await userRepository.FindAsync(x => x.UserAccount == request.Account);
            var user = user_.FirstOrDefault();

            // 判断用户是否存在
            if (user == null)
            {
                return await Task.FromResult(new ApiResult<UserDto>
                {
                    Code = EnumCode.notfound,
                    Message = "用户不存在"
                });
            }

            // 判断密码是否正确
            if (request.Password != user.UserPassword)
            {
                if (user.ErrorNums > 3)
                {
                    user.IsLocked = true;
                    await userRepository.UpdateAsync(user);
                    return await Task.FromResult(new ApiResult<UserDto>
                    {
                        Code = EnumCode.error,
                        Message = "用户已被锁定"
                    });
                }
                user.ErrorNums += 1;
                await userRepository.UpdateAsync(user);
                return await Task.FromResult(new ApiResult<UserDto>
                {
                    Code = EnumCode.error,
                    Message = $"密码错误 {user.ErrorNums} 次,还有 {4 - user.ErrorNums} 次机会。"
                });
            }

            // 登录成功，重置错误次数
            user.ErrorNums = 0;
            await userRepository.UpdateAsync(user);

            // 查询用户角色
            var roleUsers = await roleUserRepository.FindAsync(x => x.UserId == user.UserId);
            var roles = await roleRepository.GetAll();

            // 查询角色权限
            var rolePermissions = await rolePermissionRepository.GetAll();
            var permissions = await permissionRepository.GetAll();

            // 构建 UserDto
            var userDto = new UserDto
            {
                Account = user.UserAccount,
                UserNickName = user.UserNickName
            };

            //查看是否有关联的角色
            if (roleUsers.Any())
            {
                var role = roles.FirstOrDefault(r => r.RoleId == roleUsers.First().RoleId);
                if (role != null)
                {
                    userDto.RoleId = role.RoleId;
                    userDto.RoleName = role.RoleName;

                    var rolePermission = rolePermissions.FirstOrDefault(rp => rp.RoleId == role.RoleId);
                    if (rolePermission != null)
                    {
                        var permission = permissions.FirstOrDefault(p => p.PermissionId == rolePermission.PermissionId);
                        if (permission != null)
                        {
                            userDto.PermissionId = permission.PermissionId;
                            userDto.PermissionName = permission.PermissionName;
                        }
                    }
                }
            }
            return await Task.FromResult(new ApiResult<UserDto>
            {
                Code = EnumCode.success,
                Message = "登录成功",
                Data = userDto
            });
        }
    }
}
